Skip to content

Instantly share code, notes, and snippets.

@cldershem
Last active June 30, 2019 15:44
Show Gist options
  • Save cldershem/6515886 to your computer and use it in GitHub Desktop.
Save cldershem/6515886 to your computer and use it in GitHub Desktop.
going from flask-login to flask-security. I'm not clear on how to not use flask-principal. since i have to change so many different things over, i'd like to do this one piece at a time. i may end up using flask-principal in the long run..but if i don't i'd like to get this running without it.
from flask import Flask
from flask.ext.mongoengine import MongoEngine
#from flask.ext.login import LoginManager
from flask.ext.bcrypt import Bcrypt
from flask_debugtoolbar import DebugToolbarExtension
from flask.ext.mail import Mail
app = Flask(__name__)
app.config.from_object('config')
db = MongoEngine(app)
bcrypt = Bcrypt(app)
toolbar = DebugToolbarExtension(app)
mail = Mail(app)
#lm = LoginManager(app)
#lm.login_view = "users.login"
from flask.ext.security import Security, MongoEngineUserDatastore
from app.models import User
user_datastore = MongoEngineUserDatastore(db, User, User.Roles)
security = Security(app, user_datastore)
#if not app.debug:
from app import routes, models, admin # nopep8
from flask import url_for
from app import db, bcrypt
from app.constants import DATE_TIME_NOW
from flask.ext.security import UserMixin, RoleMixin
class User(db.Document, UserMixin):
class Roles(db.EmbeddedDocument, RoleMixin):
can_login = db.BooleanField(default=False)
can_comment = db.BooleanField(default=True)
can_post = db.BooleanField(default=True)
is_admin = db.BooleanField(default=False)
created_at = db.DateTimeField(required=True, default=DATE_TIME_NOW)
last_seen = db.DateTimeField(required=True, default=DATE_TIME_NOW)
firstname = db.StringField(required=True, max_length=64)
lastname = db.StringField(required=True, max_length=100)
email = db.StringField(max_length=120, unique=True)
pwdhash = db.StringField(required=True)
confirmed = db.DateTimeField(default=None)
roles = db.EmbeddedDocumentField(Roles, default=Roles)
def set_password(self, password):
self.pwdhash = bcrypt.generate_password_hash(password)
def check_password(self, password):
return bcrypt.check_password_hash(self.pwdhash, password)
def is_authenticated(self):
return True
def activate_user(self):
self.confirmed = DATE_TIME_NOW
self.roles.can_login = True
def is_active(self):
return True
def is_anonymous(self):
return False
def get_id(self):
return self.email
def __repr__(self):
return '<User %r, %r>' % (self.firstname, self.email)
def __unicode__(self):
return self.email
class Comment(db.EmbeddedDocument):
created_at = db.DateTimeField(default=DATE_TIME_NOW, required=True)
body = db.StringField(required=True)
author = db.ReferenceField(User)
def __repr__(self):
return '<Post %r>' % (self.author)
class Post(db.Document):
created_at = db.DateTimeField(default=DATE_TIME_NOW, required=True)
edited_on = db.ListField(db.DateTimeField(default=DATE_TIME_NOW))
title = db.StringField(max_length=255, required=True)
slug = db.StringField(max_length=255, required=True)
author = db.ReferenceField(User)
body = db.StringField(required=True)
tags = db.ListField(db.StringField(max_length=50))
comments = db.ListField(db.EmbeddedDocumentField(Comment))
def get_absolute_url(self):
return url_for('post', kwargs={"slug": self.slug})
def __unicode__(self):
return self.title
meta = {'allow_inheritance': True,
'indexes': ['-created_at', 'slug'],
'ordering': ['-created_at']}
def __repr__(self):
return '<Post %r, -%r>' % (self.slug, self.author)
class Page(db.Document):
created_at = db.DateTimeField(default=DATE_TIME_NOW, required=True)
edited_on = db.ListField(db.DateTimeField(default=DATE_TIME_NOW))
title = db.StringField(required=True)
slug = db.StringField(required=True)
content = db.StringField(required=True)
author = db.ReferenceField(User)
meta = {'allow_inheritance': True,
'indexes': ['-created_at', 'title'],
'ordering': ['-created_at']}
def __repr__(self):
return '<Page %r>' % (self.title)
Flask==0.10.1
Flask-Admin==1.0.6
Flask-Bcrypt==0.5.2
Flask-DebugToolbar==0.8.0
Flask-DebugToolbar-Mongo==0.1
Flask-Login==0.2.7
Flask-Mail==0.9.0
Flask-OAuth==0.12
Flask-Principal==0.4.0
Flask-Script==0.6.2
Flask-Security==1.6.9
Flask-Social==1.6.1
Flask-WTF==0.9.1
Jinja2==2.7.1
MarkupSafe==0.18
Tempita==0.5.1
WTForms==1.0.4
Werkzeug==0.9.3
amqp==1.0.13
anyjson==0.3.3
argparse==1.2.1
billiard==2.7.3.32
blinker==1.3
celery==3.0.23
celery-with-mongodb==3.0
decorator==3.4.0
facebook-sdk==0.4.0
flake8==2.0
flask-mongoengine==0.7.0
google-api-python-client==1.2
httplib2==0.8
itsdangerous==0.23
kombu==2.5.14
mccabe==0.2.1
mongoengine==0.8.3
oauth2==1.5.211
oauth2client==1.2
passlib==1.6.1
pep8==1.4.6
py-bcrypt==0.4
pyflakes==0.7.3
pymongo==2.6.1
python-dateutil==2.1
six==1.4.1
uWSGI==1.9.14
wsgiref==0.1.2
Traceback (most recent call last):
File "/home/cldershem/Documents/Development/homelessgaffer.com/hg-Python/venv/lib/python2.7/site-packages/flask/app.py", line 1836, in __call__
return self.wsgi_app(environ, start_response)
File "/home/cldershem/Documents/Development/homelessgaffer.com/hg-Python/venv/lib/python2.7/site-packages/flask/app.py", line 1820, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "/home/cldershem/Documents/Development/homelessgaffer.com/hg-Python/venv/lib/python2.7/site-packages/flask/app.py", line 1403, in handle_exception
reraise(exc_type, exc_value, tb)
File "/home/cldershem/Documents/Development/homelessgaffer.com/hg-Python/venv/lib/python2.7/site-packages/flask/app.py", line 1817, in wsgi_app
response = self.full_dispatch_request()
File "/home/cldershem/Documents/Development/homelessgaffer.com/hg-Python/venv/lib/python2.7/site-packages/flask/app.py", line 1477, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/cldershem/Documents/Development/homelessgaffer.com/hg-Python/venv/lib/python2.7/site-packages/flask/app.py", line 1381, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/home/cldershem/Documents/Development/homelessgaffer.com/hg-Python/venv/lib/python2.7/site-packages/flask/app.py", line 1475, in full_dispatch_request
rv = self.dispatch_request()
File "/home/cldershem/Documents/Development/homelessgaffer.com/hg-Python/venv/lib/python2.7/site-packages/flask_debugtoolbar/__init__.py", line 104, in dispatch_request
return view_func(**req.view_args)
File "/home/cldershem/Documents/Development/homelessgaffer.com/hg-Python/app/decorators.py", line 25, in wrapper
return func(*args, **kwargs)
File "/home/cldershem/Documents/Development/homelessgaffer.com/hg-Python/app/users/views.py", line 51, in login
login_user(user)
File "/home/cldershem/Documents/Development/homelessgaffer.com/hg-Python/venv/lib/python2.7/site-packages/flask_security/utils.py", line 64, in login_user
identity=Identity(user.id))
File "/home/cldershem/Documents/Development/homelessgaffer.com/hg-Python/venv/lib/python2.7/site-packages/blinker/base.py", line 267, in send
for receiver in self.receivers_for(sender)]
File "/home/cldershem/Documents/Development/homelessgaffer.com/hg-Python/venv/lib/python2.7/site-packages/flask_principal.py", line 469, in _on_identity_changed
self.set_identity(identity)
File "/home/cldershem/Documents/Development/homelessgaffer.com/hg-Python/venv/lib/python2.7/site-packages/flask_principal.py", line 418, in set_identity
self._set_thread_identity(identity)
File "/home/cldershem/Documents/Development/homelessgaffer.com/hg-Python/venv/lib/python2.7/site-packages/flask_principal.py", line 463, in _set_thread_identity
identity=identity)
File "/home/cldershem/Documents/Development/homelessgaffer.com/hg-Python/venv/lib/python2.7/site-packages/blinker/base.py", line 267, in send
for receiver in self.receivers_for(sender)]
File "/home/cldershem/Documents/Development/homelessgaffer.com/hg-Python/venv/lib/python2.7/site-packages/flask_security/core.py", line 172, in _on_identity_loaded
identity.provides.add(RoleNeed(role.name))
AttributeError: 'str' object has no attribute 'name'
from flask import (Blueprint, render_template, url_for, request,
redirect, flash, g, abort)
#from app import lm
from app.forms import (LoginForm, RegisterUser,
ForgotPasswordForm, ResetPasswordForm)
from app.models import (User)
#from flask.ext.login import (login_user, logout_user,
# current_user, login_required)
from app.utils import (get_activation_link, check_activation_link,
get_password_reset_link, check_password_reset_link)
from app.constants import DATE_TIME_NOW
from app.emails import email_confirmation, email_password_reset
from app.decorators import anon_required
#from app import security
from flask.ext.security import (login_required, login_user,
logout_user, current_user)
mod = Blueprint('users', __name__, url_prefix='/user')
#@lm.user_loader
#def load_user(id):
# user = User.objects.get(email=id)
# return user
@mod.before_request
def before_request():
g.user = current_user
@mod.route('/login', methods=['GET', 'POST'])
@anon_required
def login():
form = LoginForm()
page = "login"
if request.method == 'POST':
if form.validate() is False:
return render_template('users/login.html',
form=form,
page=page)
else:
user = User.objects.get(email=form.email.data.lower())
#if user and user.roles.can_login is True:
#add remember_me
user.last_seen = DATE_TIME_NOW
user.save()
login_user(user)
return redirect(request.args.get('next') or
url_for('.profile',
user=current_user.email)
)
#else:
# flash("Please confirm your email address.")
# return render_template('users/login.html',
# form=form,
# page=page)
elif request.method == 'GET':
return render_template('users/login.html',
form=form,
page=page)
def after_login(resp):
pass
@mod.route('/logout')
@login_required
def logout():
logout_user()
return redirect(url_for('index'))
@mod.route('/register', methods=['GET', 'POST'])
@anon_required
def register():
form = RegisterUser()
page = "register"
if request.method == 'POST':
if form.validate() is False:
return render_template('users/register.html',
form=form,
page=page)
else:
newUser = User(firstname=form.firstname.data.title(),
lastname=form.lastname.data.title(),
email=form.email.data.lower())
newUser.set_password(form.password.data)
newUser.save()
payload = get_activation_link(newUser)
email_confirmation(newUser, payload)
flash("Please confirm your email address.")
return redirect(url_for('index'))
elif request.method == 'GET':
return render_template('users/register.html',
form=form,
page=page)
@mod.route('/activate/<payload>')
@anon_required
def activateUser(payload):
user_email = check_activation_link(payload)
if not user_email:
return abort(404)
user = User.objects.get(email=user_email)
if user:
if user.confirmed is None:
user.activate_user()
user.save()
flash('Your account has been activated.')
else:
flash('Your account was already active.')
return redirect(url_for('.login'))
else:
return abort(404)
@mod.route('/forgotpassword', methods=['GET', 'POST'])
@anon_required
def forgotPassword():
form = ForgotPasswordForm()
page = "forgot password"
if request.method == 'POST':
if not form.validate():
return render_template('users/forgotPassword.html',
form=form,
page=page)
else:
try:
user = User.objects.get(email=form.email.data)
except:
flash("That email does not exist, please try another.")
return render_template('users/forgotPassword.html',
form=form,
page=page)
payload = get_password_reset_link(user)
email_password_reset(user, payload)
flash("Password reset email has been sent. \
Link is good for 24 hours.")
return redirect(url_for('index'))
elif request.method == 'GET':
return render_template('users/forgotPassword.html',
form=form,
page=page)
@mod.route('/resetpassword/<payload>', methods=['GET', 'POST'])
@anon_required
def reset_password(payload):
form = ResetPasswordForm()
user_email = check_password_reset_link(payload)
page = "reset password"
if not user_email:
flash("Token incorrect or has expired. Please try again.")
return redirect(url_for('.forgotPassword'))
if request.method == 'POST':
if not form.validate():
return render_template('users/resetPassword.html',
form=form,
page=page)
else:
user = User.objects.get(email=user_email)
user.set_password(form.password.data)
user.save()
#email password reset
flash("Password has been reset, please login")
return redirect(url_for('.login'))
elif request.method == 'GET':
return render_template('users/resetPassword.html',
form=form,
page=page)
@mod.route('/profile/<user>')
def profile(user):
last_seen = User.objects.get(email=user).last_seen
return render_template('users/profile.html',
user=user,
last_seen=last_seen,
page=user)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment