Skip to content

Commit v0.23

kwmccabe edited this page Apr 17, 2018 · 8 revisions

v0.23 - Add fields user_email and user_pass


Files changed (7)

File mysql/scripts/seeddata.sql MODIFIED

  • Update seed data for column user.user_email.
 DELETE FROM `user`;
-INSERT INTO `user` (keyname) VALUES ("admin");
+INSERT INTO `user` (active,keyname,user_email) VALUES (True,"admin","admin@flaskapp.com");
+INSERT INTO `user` (active,keyname,user_email) VALUES (False,"user","user@flaskapp.com");
 OPTIMIZE TABLE `user`;

File mysql/scripts/tables.sql MODIFIED

  • Add column user_email.
  • Add column user_pass.
 DROP TABLE IF EXISTS `user`;
 CREATE TABLE `user` (
     `id`            bigint(20)      NOT NULL AUTO_INCREMENT,
-    `keyname`       varchar(63)     NOT NULL,
     `active`        tinyint(1)      NOT NULL DEFAULT '1',
+    `keyname`       varchar(63)     NOT NULL,
+    `user_email`    varchar(255)    DEFAULT NULL,
+    `user_pass`     varchar(255) 	DEFAULT NULL,
 
     PRIMARY KEY (`id`),
     UNIQUE KEY `user_keyname` (`keyname`),
-    KEY `user_active` (`active`)
+    KEY `user_active` (`active`),
+    KEY `user_email` (`user_email`)
 ) ENGINE=InnoDB AUTO_INCREMENT=1000 DEFAULT CHARSET=utf8;
 DESCRIBE `user`;
 SELECT "table `user` created" AS MSG;

File web/app/user/forms.py MODIFIED

  • Add user_email to CreateUserForm and EditUserForm.
  • Add password and password2 to CreateUserForm and EditUserForm.
  • Create methods filter_useremail() and validate_usermail().
-from wtforms.validators import Email, InputRequired, Length
+from wtforms.validators import Email, EqualTo, InputRequired, Length

...

+def filter_useremail(data):
+    return str(data).lower()
+

...

+def validate_usermail(self, field):
+    if field.data != self.user.user_email and \
+            UserModel.query.filter_by(user_email=field.data).first():
+        raise ValidationError('Email address already in use.')

...
 
 class CreatUserForm(FlaskForm):
     keyname    = StringField('Username', validators=[InputRequired(),Length(2,63),validate_username], filters=[filter_username])
+    user_email = StringField('Email', validators=[InputRequired(),Length(1,63),Email(),validate_usermail], filters=[filter_useremail])
+    password   = PasswordField('Password', validators=[InputRequired(),Length(1,31),EqualTo('password2',message="Passwords must match.")])
+    password2  = PasswordField('Confirm Password')
     submit     = SubmitField('Create User')

...

 class EditUserForm(FlaskForm):
     id         = HiddenField('id')
-    keyname    = StringField('Username', validators=[InputRequired(),Length(2,63),validate_username], filters=[filter_username])
     active     = BooleanField('Active')
+    keyname    = StringField('Username', validators=[InputRequired(),Length(2,63),validate_username], filters=[filter_username])
+    user_email = StringField('Email', validators=[InputRequired(),Length(1,63),Email(),validate_usermail], filters=[filter_useremail])
+    password   = PasswordField('Password', validators=[EqualTo('password2',message="Passwords must match.")])
+    password2  = PasswordField('Confirm Password')
     submit     = SubmitField('Update User')

File web/app/user/models.py MODIFIED

  • Add columns user_email and user_pass to UserModel.
  • Add method to set user_pass via pseudo-column password and werkzeug's generate_password_hash().
  • Add method verify_password() using werkzeug's check_password_hash().
+import logging
+
 from flask import url_for
+from werkzeug.security import generate_password_hash, check_password_hash
 from .. import db
 
 
 class UserModel(db.Model):
     __tablename__ = 'user'
     id         = db.Column(db.BigInteger, autoincrement=True, primary_key=True)
-    keyname    = db.Column(db.String(63), nullable=False, unique=True, index=True, default='')
     active     = db.Column(db.Boolean, nullable=False, index=True, default=1)
+    keyname    = db.Column(db.String(63), nullable=False, unique=True, index=True, default='')
+    user_email = db.Column(db.String(255), nullable=False, unique=True, index=True)
+    user_pass  = db.Column(db.String(128))
+
+    @property
+    def password(self):
+        raise AttributeError('password is not readable')
+
+    @password.setter
+    def password(self, password):
+        logging.debug( "password.setter(%s)" %  self.user_email)
+        self.user_pass = generate_password_hash(password)
+
+    def verify_password(self, password):
+        return check_password_hash(self.user_pass, password)
 
     def to_json(self):
         json_user = {
             #'url': url_for('api.get_user', id=self.id),
             'id'        : self.id,
-            'keyname'   : self.keyname,
             'active'    : self.active,
+            'keyname'   : self.keyname,
+            'user_email': self.user_email,
         }
         return json_user

File web/app/user/templates/user_create.html MODIFIED

  • Add user_email form field.
  • Add password form field.
  • Add password2 form field.
+    <div class="form-group">
+        *{{ form.user_email.label }}
+        {{ form.user_email(class_='form-control',placeholder='a@b.c') }}
+    </div>
+    <div class="form-group">
+        *{{ form.password.label }}
+        {{ form.password(class_='form-control',placeholder='password') }}
+    </div>
+    <div class="form-group">
+        *{{ form.password2.label }}
+        {{ form.password2(class_='form-control',placeholder='confirmation') }}
+    </div>
     {{ form.submit(class_='btn btn-primary') }}

File web/app/user/templates/user_edit.html MODIFIED

  • Add user_email form field.
  • Add password form field.
  • Add password2 form field.
     <div class="form-group">
         *{{ form.keyname.label }}
-        {{ form.keyname(class_='form-control',placeholder='keyname') }}
+        {{ form.keyname(class_='form-control',placeholder='username') }}
         <p class="help-block">unique textual identifier - letters, numbers, dashes and underscores allowed - no spaces</p>
     </div>
+    <div class="form-group">
+        *{{ form.user_email.label }}
+        {{ form.user_email(class_='form-control',placeholder='a@b.c') }}
+    </div>
+    <div class="form-group">
+        {{ form.password.label }}
+        {{ form.password(class_='form-control',placeholder='password') }}
+    </div>
+    <div class="form-group">
+        {{ form.password2.label }}
+        {{ form.password2(class_='form-control',placeholder='confirmation') }}
+    </div>

File web/app/user/views.py MODIFIED

  • Remove empty password from form to prevent update.
  • Remove user_pass from column list for route/admin/user/list.
     user = UserModel.query.get_or_404(id)
     form = EditUserForm(user)
     if form.validate_on_submit():
+        if form.password.data == '':
+            del form.password
         form.populate_obj(user)
         db.session.add(user)
         db.session.commit()
 
...

 @user.route('/admin/user/view/<int:id>')
 def user_view( id ):
-    user = UserModel.query.get_or_404(id)
     cols = UserModel.__table__.columns.keys()
+    user = UserModel.query.get_or_404(id)
     return render_template('user_view.html', cols=cols, user=user)
 
...
 
 @get_list_opts('user_list_opts')
 def user_list():
     cols = UserModel.__table__.columns.keys()
+    cols_filtered = list(filter(lambda x: x not in ['user_pass'], cols))
     rows = db.session.query(UserModel)
 
...

-    return render_template('user_list.html', cols=cols,rows=rows,rowcnt=rowcnt,opts_key=opts_key)
+    return render_template('user_list.html', cols=cols_filtered,rows=rows,rowcnt=rowcnt,opts_key=opts_key)

Commit-v0.22 | Commit-v0.23 | Commit-v0.24

Clone this wiki locally