From 651c19f946f59a1832da747fdfbaa5e511517a87 Mon Sep 17 00:00:00 2001
From: Arun J <cb.en.u4cce19010@cb.students.amrita.edu>
Date: Fri, 25 Dec 2020 20:23:08 +0530
Subject: [PATCH] Add username and role columns

Other changes:
* Comparisons are case-insensitive
* Checkbox css improvements
---
 bam/forms.py                | 21 +++++++++++++++------
 bam/models.py               |  2 ++
 bam/routes.py               | 10 +++++-----
 bam/static/outform.css      | 18 +++++++++++-------
 bam/static/outlayout.css    |  1 +
 bam/templates/login.html    |  4 ++--
 bam/templates/register.html |  7 +++++--
 7 files changed, 41 insertions(+), 22 deletions(-)

diff --git a/bam/forms.py b/bam/forms.py
index d58ed3d..0abd6c0 100644
--- a/bam/forms.py
+++ b/bam/forms.py
@@ -1,11 +1,16 @@
 from flask_wtf import FlaskForm
-from wtforms import PasswordField, SubmitField, BooleanField
+from wtforms import StringField, PasswordField, SubmitField, BooleanField
 from wtforms.fields.html5 import EmailField
 from wtforms.validators import DataRequired, Length, Email, EqualTo, ValidationError
 from bam.models import User
 
 
 class RegistrationForm(FlaskForm):
+    username = StringField(
+        "Username",
+        validators=[DataRequired()],
+        render_kw={"placeholder": "Enter a username"},
+    )
     email = EmailField(
         "Email",
         validators=[DataRequired(), Email()],
@@ -24,16 +29,20 @@ class RegistrationForm(FlaskForm):
 
     submit = SubmitField("Register")
 
+    def validate_username(self, username):
+        if User.query.filter(User.username.ilike(username.data)).first():
+            raise ValidationError("Username taken - choose another.")
+
     def validate_email(self, email):
-        if User.query.filter_by(email=email.data).first():
+        if User.query.filter(User.email.ilike(email.data)).first():
             raise ValidationError("A user with this email already exists.")
 
 
 class LoginForm(FlaskForm):
-    email = EmailField(
-        "Email",
-        validators=[DataRequired(), Email()],
-        render_kw={"placeholder": "bookmaster@bam.com"},
+    username = StringField(
+        "Username",
+        validators=[DataRequired()],
+        render_kw={"placeholder": "bookmaster"},
     )
     password = PasswordField(
         "Password",
diff --git a/bam/models.py b/bam/models.py
index 8f593fa..57bff8f 100644
--- a/bam/models.py
+++ b/bam/models.py
@@ -10,7 +10,9 @@ def load_user(user_id):
 class User(db.Model, UserMixin):
     id = db.Column(db.Integer, primary_key=True)
     email = db.Column(db.String(120), unique=True, nullable=False)
+    username = db.Column(db.String(60), unique=True, nullable=False)
     password = db.Column(db.String(60), nullable=False)
+    role = db.Column(db.String(10), default="user")
 
     def __repr__(self):
         return f"User({self.email}, {self.password})"
diff --git a/bam/routes.py b/bam/routes.py
index b4ef8ff..426be32 100644
--- a/bam/routes.py
+++ b/bam/routes.py
@@ -22,12 +22,12 @@ def register():
         hashed_password = bcrypt.generate_password_hash(form.password.data).decode(
             "utf-8"
         )
-        user = User(email=form.email.data, password=hashed_password)
+        user = User(
+            username=form.username.data, email=form.email.data, password=hashed_password
+        )
         db.session.add(user)
         db.session.commit()
-        flash(
-            f"Account successfully created! You may login now.", "success"
-        )
+        flash(f"Account successfully created! You may login now.", "success")
         return redirect(url_for("login"))
     return render_template("register.html", title="Register", form=form)
 
@@ -38,7 +38,7 @@ def login():
         return redirect(url_for("home"))
     form = LoginForm()
     if form.validate_on_submit():
-        user = User.query.filter_by(email=form.email.data).first()
+        user = User.query.filter(User.username.ilike(form.username.data)).first()
         if user and bcrypt.check_password_hash(user.password, form.password.data):
             login_user(user, remember=form.remember.data)
             return redirect(url_for("home"))
diff --git a/bam/static/outform.css b/bam/static/outform.css
index c6d6ad9..5edc918 100644
--- a/bam/static/outform.css
+++ b/bam/static/outform.css
@@ -22,17 +22,15 @@ form {
 input {
   font-family: Roboto;
   font-size: 16px;
-  /* margin-bottom: 5px; */
   border-radius: 3px;
   padding: 17px;
   background-color: var(--t-dark);
   border: 1px solid black;
   color: #eee;
   transition: background 0.3s;
-  /* margin: 3px 0 10px; */
 }
 .field:hover {
-  background-color: rgba(0, 0, 0, 0.9);
+  background-color: var(--t-darker);
 }
 .field:focus,
 .field:active {
@@ -79,12 +77,13 @@ label,
   margin-top: 10px;
 }
 
-.remember-row input {
-  order: 2;
-  opacity: 0;
+.remember-row div {
+  order: 1;
 }
+
 .checkbox-indicator {
   display: flex;
+  order: 2;
   height: 1.5rem;
   width: 1.5rem;
   border: 1px solid black;
@@ -93,10 +92,15 @@ label,
   background-color: var(--t-dark);
 }
 
+.remember-row input {
+  order: 3;
+  opacity: 0;
+}
+
 .checkbox-indicator svg {
   height: 50%;
   width: 100%;
-  fill: transparent;
+  fill: #252525;
 }
 
 .remember-row:hover .checkbox-indicator {
diff --git a/bam/static/outlayout.css b/bam/static/outlayout.css
index 3edf17f..ad99454 100644
--- a/bam/static/outlayout.css
+++ b/bam/static/outlayout.css
@@ -10,6 +10,7 @@ body {
   --red: #e50914;
   --dark-red: #bb0009;
   --t-dark: rgba(0, 0, 0, 0.8);
+  --t-darker: rgba(0, 0, 0, 0.9);
 }
 
 * {
diff --git a/bam/templates/login.html b/bam/templates/login.html
index b055230..18cb33c 100644
--- a/bam/templates/login.html
+++ b/bam/templates/login.html
@@ -8,8 +8,8 @@
     {% with messages = get_flashed_messages(with_categories=True) %} {% if
     messages %} {% for category, message in messages %}
     <div class="f-message f-message-{{ category }}">{{ message }}</div>
-    {% endfor %} {% endif %} {% endwith %} {{ form.email.label() }} {{
-    form.email(class="field") }} {% for error in form.email.errors %}
+    {% endfor %} {% endif %} {% endwith %} {{ form.username.label() }} {{
+    form.username(class="field") }} {% for error in form.username.errors %}
     <div class="field-error">{{ error }}</div>
     {% endfor %} {{ form.password.label() }} {{ form.password(class="field") }}
     {% for error in form.password.errors %}
diff --git a/bam/templates/register.html b/bam/templates/register.html
index 484ff8e..a569d0f 100644
--- a/bam/templates/register.html
+++ b/bam/templates/register.html
@@ -8,8 +8,11 @@
     {% with messages = get_flashed_messages(with_categories=True) %} {% if
     messages %} {% for category, message in messages %}
     <div class="f-message f-message-{{ category }}">{{ message }}</div>
-    {% endfor %} {% endif %} {% endwith %} {{ form.email.label() }} {{
-    form.email(class="field") }} {% for error in form.email.errors %}
+    {% endfor %} {% endif %} {% endwith %} {{ form.username.label() }} {{
+    form.username(class="field") }} {% for error in form.username.errors %}
+    <div class="field-error">{{ error }}</div>
+    {% endfor %} {{ form.email.label() }} {{ form.email(class="field") }} {% for
+    error in form.email.errors %}
     <div class="field-error">{{ error }}</div>
     {% endfor %} {{ form.password.label() }} {{ form.password(class="field") }}
     {% for error in form.password.errors %}
-- 
GitLab